import os
import sys
import cv2
import math
import time
import shutil
import subprocess
import pyttsx3
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *

from widgets.subtitleWindow import SubtitleWindow
from widgets.clipWindow import ClipWindow
from moviepy.editor import AudioClip,AudioFileClip,concatenate_audioclips,CompositeAudioClip,\
    ImageSequenceClip,VideoFileClip,TextClip,CompositeVideoClip

class ConvertProgress(QWidget):
    def __init__(self):
        super(ConvertProgress,self).__init__()
        # self.setStyleSheet(
        #     'QWidget{background-color:rgb(75,75,75);color:rgb(200,200,200)}')
        # self.setWindowTitle('提交中...')
        self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowMinimizeButtonHint)
        self.setWindowTitle('生成序列')
        self.setMinimumWidth(500)
        self.mainLayout=QVBoxLayout()
        self.mainLayout.setContentsMargins(15,12,15,15)
        self.tip_label=QLabel("生成序列：")
        self.tip_label.setAlignment(Qt.AlignCenter)
        self.progress_layout=QHBoxLayout()

        self.p=QProgressBar()

        self.mainLayout.addWidget(self.tip_label)
        self.mainLayout.addWidget(self.p)
        self.setLayout(self.mainLayout)

    def setValue(self,value):
        self.p.setValue(value)


class ConvertImages(QThread):

    def __init__(self, imgsdir,vc):# videopath,
        super(ConvertImages, self).__init__()
        # self.videopath = videopath
        self.imgsdir = imgsdir
        self.vc=vc
        self.count=1


    def run(self):
        if self.vc.isOpened():
            rval, frame = self.vc.read()
        else:
            rval = False
        try:
            while rval:
                rval, frame = self.vc.read()
                outpath = os.path.join(self.imgsdir, str(self.count) + '.png')
                # print('outpath:',outpath)
                cv2.imwrite(outpath, frame)
                self.count = self.count + 1
                cv2.waitKey(1)
        except Exception as convertSequence_ERR:
            print('convertSequence_ERR:', self.count, convertSequence_ERR)
        finally:
            self.vc.release()

    # def run(self):
    #     while self.count<100:
    #         time.sleep(0.1)
    #         self.count+=1
    #         print('count:',self.count)


class ImageItem(QGraphicsItem):
    def __init__(self,img_path,width,height):
        super(ImageItem, self).__init__()
        # self.uid=uid
        # self.rect=rect
        self.img_path=img_path
        self.width=width
        self.height=height
        self.rect=QRectF(0,0,width,height)
        self.setAcceptDrops(True)
        self.setFlag(QGraphicsItem.ItemIsSelectable, True)

        # self.setFlag(QGraphicsItem.ItemIsMovable, True)
        # self.data={'uuid':self.uid,'rect':self.rect,'pos':self.pos(),'attr':self.attr,'deep':self.deep}

    def boundingRect(self):
        # if self.customLength > 0:
        #     self.width=self.customLength*self.ui_width#
        # return QRectF(0, 0, (self.width / self.scale()) - 20, self.height / self.scale())
        return self.rect

    def paint(self, QPainter, QStyleOptionGraphicsItem, widget=None):
        # 选中状态变色
        pen = QPen()
        if self.isSelected():
            # print('SSS')
            pen.setColor(QColor('#B0C4DE'))
            pen.setWidth(2)
        font = QFont('', 15)
        QPainter.setPen(pen)

        QPainter.setFont(font)
        # QPainter.setBrush(QBrush(QColor(self.color)))

        QPainter.drawRect(self.rect)
        img=QPixmap(self.img_path)
        # QPainter.drawPixmap(0, 0, self.rect.width(), self.rect.height(), img)
        QPainter.drawPixmap(0, 0, self.width, self.height, img)
        # QPainter.drawText(self.rect, Qt.AlignCenter, self.deep)

    def set_imgpath(self,imgpath):
        self.img_path=imgpath
        self.update()

    def dragEnterEvent(self, QGraphicsSceneDragDropEvent):
        QGraphicsSceneDragDropEvent.setAccepted(True)


class SubtitleItem(QGraphicsItem):
    def __init__(self,data,width,height):
        super(SubtitleItem, self).__init__()
        self.width=width
        self.height=height
        self.rect=QRectF(0,0,width,height)
        self.data=data
        self.text=data['subtitle']
        self.duration=data['duration']
        self.mp3=data['mp3']
        self.start_frame=1  #显示起始帧
        self.end_frame=10000  #显示结束帧
        self.data['start_frame'] = self.start_frame  #将起始与结束帧加入data里
        self.data['end_frame'] = self.end_frame
        self.assigned=-1   #是否已分配时间,默认没有分配为-1

        self.setAcceptDrops(True)
        self.setFlag(QGraphicsItem.ItemIsSelectable, True)
        self.setFlag(QGraphicsItem.ItemIsMovable, True)


    def boundingRect(self):
        # if self.customLength > 0:
        #     self.width=self.customLength*self.ui_width#
        # return QRectF(0, 0, (self.width / self.scale()) - 20, self.height / self.scale())
        return self.rect

    def paint(self, QPainter, QStyleOptionGraphicsItem, widget=None):
        # 选中状态变色
        pen = QPen()
        if self.isSelected():
            # print('SSS')
            pen.setColor(QColor('#B0C4DE'))
            pen.setWidth(2)
        if self.assigned==1:
            pen.setColor(QColor('#FFA500'))
        else:
            pen.setColor(QColor('#FFFFF0'))
        font = QFont('', 15)
        QPainter.setPen(pen)
        QPainter.setFont(font)
        QPainter.drawRoundedRect(self.boundingRect(),15,15)
        QPainter.drawText(self.boundingRect(), Qt.AlignCenter, self.text)

    def set_imgpath(self,imgpath):
        self.img_path=imgpath
        self.update()

    def pre_assiged(self,current_frame,fps):
        if self.assigned==-1:
            self.start_frame=current_frame
            self.end_frame=self.start_frame + int(fps*self.duration)
        else:
            self.start_frame=1
            self.end_frame=10000
        self.assigned*=-1
        self.data['start_frame'] = self.start_frame
        self.data['end_frame'] = self.end_frame


    # def keyPressEvent(self, QKeyEvent):
    #     print('有按键')
    #     if QKeyEvent.key() ==Qt.Key_S:
    #         print('按下了S')
    #         if self.assigned==-1:
    #             view=self.scene().views()[0]
    #             timeLine=view.parent
    #             self.start_frame=timeLine.current_frame
    #             fps=timeLine.data['fps']
    #             self.end_frame=int(fps*self.duration)
    #         else:
    #             self.start_frame=1
    #             self.end_frame=10000
    #         self.assigned*=-1
    #     super(SubtitleItem, self).keyPressEvent(QKeyEvent)

class BgmItem(QGraphicsItem):
    def __init__(self,data,width,height):
        super(BgmItem, self).__init__()
        self.width=width
        self.height=height
        self.rect=QRectF(0,0,width,height)
        self.data=data
        self.text=data['subtitle']
        self.duration=data['duration']
        self.mp3=data['mp3']
        self.start_frame=1  #显示起始帧
        self.end_frame=10000  #显示结束帧
        self.data['start_frame'] = self.start_frame  #将起始与结束帧加入data里
        self.data['end_frame'] = self.end_frame
        self.assigned=-1   #是否已分配时间,默认没有分配为-1

        self.setAcceptDrops(True)
        self.setFlag(QGraphicsItem.ItemIsSelectable, True)
        self.setFlag(QGraphicsItem.ItemIsMovable, True)


    def boundingRect(self):

        return self.rect

    def paint(self, QPainter, QStyleOptionGraphicsItem, widget=None):
        # 选中状态变色
        pen = QPen()
        if self.isSelected():
            # print('SSS')
            pen.setColor(QColor('#B0C4DE'))
            pen.setWidth(2)
        if self.assigned==1:
            pen.setColor(QColor('#32CD32'))
        else:
            pen.setColor(QColor('#FFFF00'))
        font = QFont('', 10)
        QPainter.setPen(pen)
        QPainter.setFont(font)
        QPainter.drawRoundedRect(self.boundingRect(),15,15)
        QPainter.drawText(self.boundingRect(), Qt.AlignCenter, self.text)

    def set_imgpath(self,imgpath):
        self.img_path=imgpath
        self.update()

    def pre_assiged(self,current_frame,fps):
        if self.assigned==-1:
            self.start_frame=current_frame
            self.end_frame=self.start_frame + int(fps*self.duration)
        else:
            self.start_frame=1
            self.end_frame=10000
        self.assigned*=-1
        self.data['start_frame'] = self.start_frame
        self.data['end_frame'] = self.end_frame



class GraphicView(QGraphicsView):
    # current_artist_Signal = pyqtSignal(str)

    def __init__(self,engine,parent=None):
        super(GraphicView, self).__init__(parent)
        #全局变量
        self.engine=engine
        self.parent = self.parent()
        self.videopath=''  #原始视频路径
        self.color_map={'Ground':'#5d422d','Sea':'#1d5291','River':'#798ba0','Mountain':'#d8b783','Grass':'#5bed1d','Sky':'#a0eef3'}
        self.w=self.h=1000
        self.begin_draw=False #开始绘制
        self.draw_points=[]  #每次点击的点
        self.drawing=-1  #当前是否处于绘制模式
        self.project_path=''  #当前项目的目录
        self.audioClips_path=''  #d=当前的audioClips路径
        self.imgsdir=''  #当前序列的目录
        self.frames=0  #总帧数
        self.width=0  #当前视频宽度
        self.height=0  #当前视频高度
        self.img_item=None  #当前视图的图片item
        self.imgs_path_list=[]  #当前所有图片的路径列表
        # self.setMaximumSize(1920, 1080)
        # self.setFixedSize(1920,1080)
        self.setMinimumWidth(self.w)
        self.setMinimumHeight(self.h)
        self.setStyleSheet('GraphicView{background-color:#DCDCDC}'
                                       'QScrollBar{width:1px}')
        self.setDragMode(QGraphicsView.RubberBandDrag)
        self.setRenderHint(QPainter.Antialiasing)
        self.setRenderHint(QPainter.TextAntialiasing)
        self.setStyleSheet("padding:0px;border:0px")
        self.setViewportUpdateMode(QGraphicsView.FullViewportUpdate)  # 全视图，可以消除残影
        self.setTransformationAnchor(QGraphicsView.AnchorUnderMouse)
        self.setMouseTracking(1)
        self.setAcceptDrops(True)

        # self.acceptDrops()

        self.scene=QGraphicsScene()

        self.setScene(self.scene)
        self.scene.setSceneRect(QRectF(0,0,1500,1500))
        # self.init_center()
        #计时器
        self.timer=QBasicTimer()
        #进度条
        self.prog=ConvertProgress()




    #拖入外部文件
    def dragEnterEvent(self, QDragEnterEvent):
        # print(QDragEnterEvent.source())
        if self.project_path: #当存在项目目录时
            # print('imgsdir:',self.imgsdir)
            things=QDragEnterEvent.mimeData().text()
            # print(things)
            if things.endswith(".mov") or things.endswith('.mp4'):#or things.endswith('.fbx')
                print('drag in') #https://blog.csdn.net/chengmo123/article/details/93468426
                QDragEnterEvent.accept()
                self.videopath=things.split('file:///')[1]
                print('videopath:',self.videopath)
                if not os.path.exists(self.imgsdir):
                    os.makedirs(self.imgsdir)
                vc = cv2.VideoCapture(self.videopath)
                self.fps = int(vc.get(cv2.CAP_PROP_FPS))
                self.frames = vc.get(cv2.CAP_PROP_FRAME_COUNT)
                self.width = vc.get(cv2.CAP_PROP_FRAME_WIDTH)
                self.height = vc.get(cv2.CAP_PROP_FRAME_HEIGHT)
                print(self.fps,self.frames,type(self.width),self.height)
                if self.width > 1500:
                    self.width=self.width/2
                    self.height=self.height/2
                #开启进度条
                print('开启进度条')
                self.prog.show()
                self.prog.move(self.parent.width()/2+self.parent.pos().x()-self.prog.width()/2, self.parent.height()/2+self.parent.pos().y()-self.prog.height()/2)
                self.timer.start(10, self)
                self._thread = ConvertImages(self.imgsdir,vc) #videopath, imgsdir,vc
                self._thread.start()

        super(GraphicView, self).dragEnterEvent(QDragEnterEvent)
    #
    # #拖入items
    def dropEvent(self, QDropEvent):  #这个需要有item在才能生成我日了
        """
        拖入音频文件
        :param QDropEvent:
        :return:
        """
        # QDropEvent.accept()
        QDropEvent.setAccepted(True)
        print('连触发都没有吗')
        from_widget = QDropEvent.source()
        print(from_widget)
        if isinstance(from_widget, QListWidget):
            print('是从任务组里拖任务出来了')
            dropItems=from_widget.selectedItems()
            # first_item=dropItems[0]#第一个item
            for listitem in dropItems:
                data=listitem.data(5)
                print(data)
                # subtitle=data['subtitle']
                # duration=data['duration']
                atype=data['atype']
                if atype=='clip':
                    item=SubtitleItem(data,self.width-20,50)
                elif atype=='bgm':
                    item=BgmItem(data,self.width-20,20)
                self.scene.addItem(item)
                item.setPos(QDropEvent.pos())
        super(GraphicView, self).dropEvent(QDropEvent)


    def timerEvent(self, *args, **kwargs):
        percent=int(self._thread.count*100.0/self.frames)
        self.prog.setValue(percent)
        if percent>95:
            self.prog.close()
            # self.close()
            self.timer.stop()
            QMessageBox.information(None,'提示','转化完成')
            # self.parent.set_frame(self.frames)  #设置当前总帧数
            self.createImgItem()
            data = {'videopath':self.videopath,'frames': self.frames, 'width': self.width, 'height': self.height,'fps':self.fps}
            self.parent.setVideoData(data)
            temp_mp4=os.path.join(self.project_path,'temp','temp.mp4')
            shutil.copyfile(self.videopath,temp_mp4)    #不能copy，copy的会带原声音，要去掉原声音？将原视频复制到temp目录下，之后合成就都用该视频输出


    def createImgItem(self):
        """
        拖入生成ImgItem
        :return:
        """

        img_dir=self.imgsdir#, img_name = os.path.split(self.imgsdir)
        # img_type = os.path.splitext(img_name)[1]
        img_list = [n for n in os.listdir(img_dir)]
        sort_img = sorted(img_list, key=lambda x: int(x.split('.')[0]))
        print('img_list:', img_list)
        print('sort_img:', sort_img)
        self.imgs_path_list = [os.path.join(img_dir, i) for i in sort_img]  # 获取当前所有序列列表
        first_img_path = os.path.join(img_dir, sort_img[0])
        print('first_img_path:', first_img_path)
        # vc = cv2.imread(img_path, cv2.IMREAD_UNCHANGED)
        # self.frames = len(sort_img)
        # self.width = vc.shape[1] if vc.shape[1] < 1500 else vc.shape[1] / 2  # 注意 这里shape的高，宽即row,column读取方法
        # self.height = vc.shape[0] if vc.shape[1] < 1500 else vc.shape[0] / 2  # 当宽度超过1500时，就取一半
        print(self.frames, self.width, self.height)
        data = {'videopath':self.videopath,'frames': self.frames, 'width': self.width, 'height': self.height,'fps':self.fps}
        try:
            self.img_item = self.getImgItem()
            if not self.img_item:
                self.img_item = ImageItem(first_img_path, self.width, self.height)
                self.scene.addItem(self.img_item)
                self.img_item.setPos((self.scene.width() - self.width) / 2, (self.scene.width() - self.height) / 2)
                print('生成item完成')
            self.parent.setVideoData(data)
        except Exception as createImgItem_ERR:
            print('createImgItem_ERR:', createImgItem_ERR)



    def contextMenuEvent(self, QContextMenuEvent):
        rMenu = QMenu()
        createProjectAction=QAction(u'设置工程',None)
        createProjectAction.triggered.connect(self.create_project)
        importVideoAction=QAction(u'导入视频',None)
        importVideoAction.triggered.connect(self.import_video)
        importImgsAction=QAction(u'导入序列',None)
        importImgsAction.triggered.connect(self.import_imgs)
        clipWindowAction=QAction(u'音视频剪辑',None)
        clipWindowAction.triggered.connect(self.open_clipWindow)
        subtitleAudioAction=QAction(u'字幕音频',None)
        subtitleAudioAction.triggered.connect(self.open_subtitleWindow)
        refreshAction=QAction(u'刷新列表',None)
        refreshAction.triggered.connect(self._refresh_list)
        oepnProjectAction=QAction(u'查看工程',None)
        oepnProjectAction.triggered.connect(self.open_project)
        compositeVideoAction=QAction(u'合成视频',None)
        compositeVideoAction.triggered.connect(self.composite_video)
        # testAction = QAction(u'test', None)
        # testAction.triggered.connect(self.test)
        rMenu.addAction(createProjectAction)
        rMenu.addAction(importVideoAction)
        rMenu.addAction(importImgsAction)
        rMenu.addAction(subtitleAudioAction)
        rMenu.addAction(refreshAction)
        rMenu.addAction(oepnProjectAction)
        rMenu.addAction(compositeVideoAction)
        # rMenu.addAction(testAction)
        rMenu.exec(QCursor.pos())

    def create_project(self):
        dir=QFileDialog.getExistingDirectory(self,'选择目录')
        print(dir)
        if dir:
            default_dirs=['audioClips','imgs','output','temp','videoClips']  #分别存储音频,序列，输出mp4
            for d in default_dirs:
                new_dir=os.path.join(dir,d)
                if not os.path.exists(new_dir):
                    os.makedirs(new_dir)
                if d=='audioClips':
                    default_dir=os.path.join(new_dir,'default')
                    if not os.path.exists(default_dir):
                        os.makedirs(default_dir)
                    bgm_dir=os.path.join(new_dir,'bgm')
                    if not os.path.exists(bgm_dir):
                        os.makedirs(bgm_dir)
            self.project_path=dir
            self.audioClips_path=os.path.join(self.project_path,'audioClips')
            self.imgsdir=os.path.join(self.project_path,'imgs')
            self.parent.set_project(dir)
            #刷新默认音频列表
            # audioClips_path = os.path.join(self.project_path, 'audioClips')
            try:
                self.scene.clear()   #每次设置工程则清空场景
                self.parent.update_subtitle_list()
                self.parent._show_clips('default')
                QMessageBox.information(None,'提示','设置成功')
            except Exception as create_project_ERR:
                print(str(create_project_ERR))


    def import_video(self):
        """
        不拖入，直接选择视频
        :return:
        """
        if self.project_path:
            fileName = QFileDialog.getOpenFileName(None, "请选择视频", ".", "(*)")
            print(fileName)
            if fileName[0]:
                self.videopath=fileName[0]
                print('videopath:',self.videopath)
                if not os.path.exists(self.imgsdir):
                    os.makedirs(self.imgsdir)
                vc = cv2.VideoCapture(self.videopath)
                self.fps = int(vc.get(cv2.CAP_PROP_FPS))
                self.frames = vc.get(cv2.CAP_PROP_FRAME_COUNT)
                self.width = vc.get(cv2.CAP_PROP_FRAME_WIDTH)
                self.height = vc.get(cv2.CAP_PROP_FRAME_HEIGHT)
                print(self.fps,self.frames,type(self.width),self.height)
                if self.width > 1500:
                    self.width=self.width/2
                    self.height=self.height/2
                #开启进度条
                print('开启进度条')
                self.prog.show()
                self.prog.move(self.parent.width()/2+self.parent.pos().x()-self.prog.width()/2, self.parent.height()/2+self.parent.pos().y()-self.prog.height()/2)
                self.timer.start(10, self)
                self._thread = ConvertImages(self.imgsdir,vc) #videopath, imgsdir,vc
                self._thread.start()


    def import_imgs(self):
        """
        直接读取
        :return:
        """
        if self.project_path:
            fileName = QFileDialog.getOpenFileName(None, "选择序列其中一张图片", ".", "(*)")
            print(fileName)
            if fileName[0]:
                img_path=fileName[0]
                img_dir,img_name=os.path.split(img_path)
                img_type=os.path.splitext(img_name)[1]
                img_list=[n for n in os.listdir(img_dir) if n.endswith(img_type)]
                sort_img=sorted(img_list,key=lambda x:int(x.split('.')[0]))
                print('img_list:',img_list)
                print('sort_img:',sort_img)
                self.imgs_path_list=[os.path.join(img_dir,i) for i in sort_img]    #获取当前所有序列列表
                first_img_path=os.path.join(img_dir,sort_img[0])
                print('first_img_path:',first_img_path)
                self.fps=25 ##默认fps=25
                vc=cv2.imread(img_path,cv2.IMREAD_UNCHANGED)
                self.frames = len(sort_img)
                self.width = vc.shape[1] if vc.shape[1]<1500 else vc.shape[1]/2 #注意 这里shape的高，宽即row,column读取方法
                self.height = vc.shape[0] if vc.shape[1]<1500 else vc.shape[0]/2  #当宽度超过1500时，就取一半
                print(self.frames,self.width,self.height)
                data={'frames':self.frames,'width':self.width,'height':self.height,'fps': self.fps}  #默认fps=25
                try:
                    self.img_item=self.getImgItem()

                    if not self.img_item:
                        self.img_item=ImageItem(first_img_path,self.width,self.height)
                        self.scene.addItem(self.img_item)
                        self.img_item.setPos((self.scene.width()-self.width)/2,(self.scene.width()-self.height)/2)
                        print('生成item完成')
                    self.parent.setVideoData(data)
                    self.parent.create_temp_mp4()
                except Exception as import_imgs_ERR:
                    print('import_imgs_ERR:',import_imgs_ERR)
        else:
            QMessageBox.information(None, '提示', '请先设置工程')



    def open_project(self):
        self.parent.open_project()

    def _refresh_list(self):
        if self.project_path:
            self.parent.update_subtitle_list()
            self.parent._show_clips('default')

    def open_clipWindow(self):
        if self.project_path:
            self.clipWindow=ClipWindow()
            self.clipWindow.show()

    def open_subtitleWindow(self):
        if self.project_path:
            try:
                audioClips_path=os.path.join(self.project_path,'audioClips')
                self.subtiteWindow=SubtitleWindow(audioClips_path,self.engine,parent=self.parent)
                self.subtiteWindow.show()

            except Exception as open_subtitleWindow_ERR:
                print(str(open_subtitleWindow_ERR))
        else:
            QMessageBox.information(None,'提示','请先设置工程')

    def check_audio(self):
        """
        检测所有以排列好的item,看是否有帧数穿插
        :return:
        """
        all_audio_list=[]  #根据帧数对，排序过后的帧数列表
        temp_list=[]  #缓存所有帧数对，用于判断是否穿插
        all_item_temp_list=[]  #缓存所有item用以排序，item来获取对应的audio来进行合成
        all_sorted_item_list=[]   #所有排序正确的item,用来直接读取起始时间用以合成audio与字幕
        bgm_list=[]  #背景音乐
        for i in self.scene.items():
            if isinstance(i,SubtitleItem):
                start_frame=i.start_frame
                end_frame=i.end_frame
                temp_list.append((start_frame,end_frame))
                all_item_temp_list.append(i)
            elif isinstance(i,BgmItem):
                # start_frame=i.start_frame
                # end_frame=i.end_frame
                # temp_list.append((start_frame,end_frame))

                bgm_list.append(i.data)

        all_audio_list=sorted(temp_list,key=lambda x :x[0])
        # print('all_audio_list:',all_audio_list)
        all_frame_list=[]
        for t in all_audio_list:
            all_frame_list.append(t[0])
            all_frame_list.append(t[1])
        sort_all_frame_list=sorted(all_frame_list)
        # print('all_frame_list:',all_frame_list)
        # print('sort_all_frame_list:',sort_all_frame_list)
        if all_frame_list==sort_all_frame_list:
            all_sorted_item_list=sorted(all_item_temp_list,key=lambda t:t.start_frame)
            data_list=[d.data for d in all_sorted_item_list]   #返回正确的item的data
            if bgm_list:
                data_list.extend(bgm_list)#添加上bgm数据
            return data_list
        else:
            wrong_frame_list = []
            for i in range(len(all_frame_list)):
                if all_frame_list[i] != sort_all_frame_list[i]:
                    wrong_frame_list.append(all_frame_list[i])
            print(wrong_frame_list)
            QMessageBox.information(None,"错误",'帧数{}之间有声音重叠，请检测'.format(wrong_frame_list))
            # print('帧数{}之间有声音重叠，请检测'.format(wrong_frame_list))
            return []

    def create_temp_audio_mp3(self,data,duration):
        """
        生成所有音频音频
        :param data:
        :param duration:
        :return:
        """
        if data:
            temp_mp3=os.path.join(self.project_path,'temp','temp_audito.mp3')


    def create_output_mp4(self,data):
        """
        先生成带字幕的无音视频
        :param data: 按先后顺序的字幕数据[{'start_frame':xx,'subtitle':xxx,'duration':xx,'start_frame':start_frame,'mp3':xx},{}]
        :return:
        """
        temp_subtitle_path=''
        if data:
            temp_mp4=os.path.join(self.project_path,'temp','temp.mp4')
            v_clip = VideoFileClip(temp_mp4)   #获取视频
            v_clip_list=[v_clip]
            a_clip=v_clip.audio   #视频带的音频
            if not a_clip:   #当音频不存在时，生成音频
                #生成空音频
                blank_audit_mp3=os.path.join(self.project_path, 'temp', 'blank_audio.mp3')
                make_frame = lambda t: 2 * ([0 * t])
                blank_clip = AudioClip(make_frame, duration=v_clip.duration, fps=44100)
                blank_clip.write_audiofile(blank_audit_mp3)
                a_clip=AudioFileClip(blank_audit_mp3)

            a_clip_list=[a_clip]
            for i in data:
                atype=i['atype']
                duration =i['duration']
                start_frame=i['start_frame']
                subtitle=i['subtitle']
                mp3_path=i['mp3']
                print('mp3_path:',mp3_path)
                start=start_frame*1.0/self.fps  #起始秒数
                #视频
                if atype!='bgm':
                    t_clip = TextClip(subtitle, color='white', font='Microsoft-YaHei-&-Microsoft-YaHei-UI', kerning=5,
                                      fontsize=30, align='center').set_position(
                        ("center", "bottom"))
                    v_clip_list.append(t_clip.subclip(0,duration).set_start(start))

                #音频
                i_clip = AudioFileClip(mp3_path)   #单个对应的音频
                a_clip_list.append(i_clip.set_start(start))
            #生成字幕无音视频
            new_vClip = CompositeVideoClip(v_clip_list,duration=v_clip.duration)
            out_subtitle_mp4=os.path.join(self.project_path,'temp','temp_subtitle.mp4')
            new_vClip.write_videofile(out_subtitle_mp4)
            temp_subtitle_path = out_subtitle_mp4

            #生成音频
            out_audio_mp3 = os.path.join(self.project_path, 'temp', 'temp_audio.mp3')
            audio_clip=CompositeAudioClip(a_clip_list)
            audio_clip.write_audiofile(out_audio_mp3, fps=44100)
            temp_audio_path = out_audio_mp3

            #合成最终视频
            output_mp4=os.path.join(self.project_path, 'output', 'output.mp4')
            cmd = 'ffmpeg -i {} -i {}  -y  {}'.format(temp_audio_path, temp_subtitle_path, output_mp4)
            os.popen(cmd)
        # return temp_subtitle_path,temp_audio_path

    def composite_video(self):
        """
        合成视频输出
        :return:
        """
        data=self.check_audio()
        print('composite_video:',data)
        if data:
            self.create_output_mp4(data)
            # temp_subtitle_path=self.create_temp_subtitle_mp4(data)  #生成无音带字幕视频
            # if temp_subtitle_path:
            #     print('生成无音带字幕视频')
            #     self.create_output_mp4()


    def getImgItem(self):
        """
        获取当前的主图片item
        :return: imgItem
        """
        item=None
        items=self.scene.items()
        if items:
            for i in self.scene.items():
                if isinstance(i,ImageItem):
                    item=i
        return item

    def updateImg(self,number):
        """
        更新ImgItem中的图片
        :param number:
        :return:
        """
        if self.imgs_path_list:
            self.img_item.set_imgpath(self.imgs_path_list[number-1])
            # print('number:',number)

    def updateSubtitle(self,value):
        # print('updateSubtitle:',value)
        items=self.scene.items()
        if items:
            for i in items:
                if isinstance(i,SubtitleItem):
                    if i.start_frame<=value and i.end_frame>=value:
                        i.setVisible(True)
                    else:
                        i.setVisible(False)

    def keyPressEvent(self, QKeyEvent):
        print('view中keypress')
        if QKeyEvent.key()==Qt.Key_S:
            sitems=self.scene.selectedItems()
            if sitems:
                i=sitems[0]
                if isinstance(i,SubtitleItem) or isinstance(i,BgmItem):
                    i.pre_assiged(self.parent.current_frame,self.parent.data['fps'])

        if QKeyEvent.key()==Qt.Key_Space:
            sitems=self.scene.selectedItems()
            if sitems:
                i=sitems[0]
                if isinstance(i,SubtitleItem):
                    self.engine.say(i.text)
                    self.engine.runAndWait()
                elif isinstance(i,BgmItem):
                    self.engine.say('这是bgm'+i.text)
                    self.engine.runAndWait()

        super(GraphicView, self).keyPressEvent(QKeyEvent)

    def mousePressEvent(self, QMouseEvent):
        if self.img_item:
            pos=QMouseEvent.pos()
            print(self.img_item.width,self.img_item.height)
            print(pos.x(),pos.y())
            super(GraphicView, self).mousePressEvent(QMouseEvent)


    def test(self):
        print('OK')
        # print(parent)
        # self.parent.set_frame(1000)
        # video = cv2.VideoCapture(r"D:\BaiduNetdiskDownload\小丑.韩版.Joker.2019.HD1080P.X264.AAC.English.CHS.Mp4Ba.mp4")
        # total_s = video.get(cv2.CAP_PROP_FRAME_COUNT)
        # print(total_s)

        self.createImgItme(self.imgsdir + '1.png', self.width, self.height)

class StartRefreshMovie(QSplashScreen):
    def __init__(self):
        super(StartRefreshMovie, self).__init__()
        self.IMGS_PATH=os.path.join(os.path.dirname(__file__),'imgs')
        self.start_img=os.path.join(self.IMGS_PATH,'cgai.png')
        print(self.start_img)
        #
        self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowMinimizeButtonHint | Qt.WindowStaysOnTopHint)
        self.setAttribute(Qt.WA_TranslucentBackground)
        self.main_layout=QVBoxLayout()


        # self.gif = QMovie(self.start_img)
        self.gif_label=QLabel()
        self.gif_label.setAlignment(Qt.AlignCenter)
        self.gif_label.setScaledContents(True)
        self.gif_label.setMaximumWidth(150)
        self.gif_label.setMaximumHeight(150)
        center=QDesktopWidget().availableGeometry().center()
        self.gif_label.move(center)
        # self.gif_label.setMovie(self.gif)
        # self.gif.start()
        self.gif_label.setPixmap(QPixmap(self.start_img))
        self.main_layout.addWidget(self.gif_label)
        self.setLayout(self.main_layout)
        self.show()
    def mousePressEvent(self, evt):
        pass
        # 重写鼠标点击事件，阻止点击后消失
    def mouseDoubleClickEvent(self, *args, **kwargs):
        pass
        # 重写鼠标移动事件，阻止出现卡顿现象
    def enterEvent(self, *args, **kwargs):
        pass
        # 重写鼠标移动事件，阻止出现卡顿现象
    def mouseMoveEvent(self, *args, **kwargs):
        pass


class RefreshMovie(QSplashScreen):
    """
    显示载入
    """
    def __init__(self):
        super(RefreshMovie, self).__init__()
        #
        self.IMGS_PATH=os.path.join(os.path.dirname(os.path.dirname(__file__)),'imgs')
        self.refresh_gif=os.path.join(self.IMGS_PATH,'re.gif')
        #
        self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowMinimizeButtonHint | Qt.WindowStaysOnTopHint)
        self.setAttribute(Qt.WA_TranslucentBackground)
        self.main_layout=QVBoxLayout()
        # self.setMaximumWidth(30)
        # self.setMaximumHeight(30)

        self.gif = QMovie(self.refresh_gif)
        self.gif_label=QLabel()
        self.gif_label.setAlignment(Qt.AlignCenter)
        self.gif_label.setScaledContents(True)
        self.gif_label.setMaximumWidth(50)
        self.gif_label.setMaximumHeight(50)
        self.gif_label.setMovie(self.gif)
        self.gif.start()
        self.main_layout.addWidget(self.gif_label)
        self.setLayout(self.main_layout)
        self.show()
    def mousePressEvent(self, evt):
        pass
        # 重写鼠标点击事件，阻止点击后消失
    def mouseDoubleClickEvent(self, *args, **kwargs):
        pass
        # 重写鼠标移动事件，阻止出现卡顿现象
    def enterEvent(self, *args, **kwargs):
        pass
        # 重写鼠标移动事件，阻止出现卡顿现象
    def mouseMoveEvent(self, *args, **kwargs):
        pass


class MySlider(QSlider):

    def __init__(self, director):
        super(MySlider, self).__init__()
        # self.setLayoutDirection(director)

        self.setOrientation(director)

    def mousePressEvent(self, QMouseEvent):
        x = QMouseEvent.pos().x()
        per = x * 1.0 / self.width()
        value = per * (self.maximum() - self.minimum()) + self.minimum()
        self.setValue(int(value))

        super(MySlider, self).mousePressEvent(QMouseEvent)

# class SubtitleList(QListWidget):
#
#     def __init__(self):
#         super(SubtitleList, self).__init__()
#         self.setContextMenuPolicy(Qt.CustomContextMenu)  # 开启自定义右击菜单
#         self.customContextMenuRequested.connect(self.right_menu)
#



class TimeLine(QWidget):

    def __init__(self):
        super(TimeLine, self).__init__()
        self.all_frame=0
        self.project_dir=''
        self.data={'fps':25}  #配置数据{'fps':25,'frames':xx,'width':xx,'height':xx},默认fps25
        self.clip_dir_path = 'default'  #当前选择的clips目录,默认是default
        self.current_frame=0  #当前帧数
        #初始化音文本引擎
        self.engine = pyttsx3.init()
        self.engine.setProperty('voice', 'zh')
        rate = self.engine.getProperty('rate')
        self.engine.setProperty('rate', rate - 30)
        volume = self.engine.getProperty('volume')
        print('rate,volume:',rate,volume)
        self.engine.setProperty('volume', volume + 0.55)
        # self.engine.stop()

        self.setWindowTitle('字幕语音合成')
        icon_path=os.path.join(os.path.dirname(__file__),'imgs','cgai.png')
        self.icon=QIcon(icon_path)
        self.setWindowIcon(self.icon)
        self.main_layout=QHBoxLayout()
        self.left_layout=QVBoxLayout()
        self.down_layout=QVBoxLayout()

        self.graph = GraphicView(self.engine,parent=self)
        self.timeline_layout=QHBoxLayout()
        self.current_frame_label=QLabel('1')
        self.current_frame_label.setAlignment(Qt.AlignCenter)
        self.start_label=QLabel('1')
        self.timeline=MySlider(Qt.Horizontal)
        self.timeline.setMinimum(1)
        self.timeline.setSingleStep(1)
        self.timeline.setTickPosition(QSlider.TicksAbove)#QSlider.TicksBelow
        self.timeline.setTickInterval(10)
        self.timeline.valueChanged.connect(self.timeline_changed)  #事件放预设后面
        self.end_label=QLabel('X')
        self.timeline_layout.addWidget(self.start_label)
        self.timeline_layout.addWidget(self.timeline)
        self.timeline_layout.addWidget(self.end_label)
        self.down_layout.addWidget(self.current_frame_label)
        self.down_layout.addLayout(self.timeline_layout)
        self.left_layout.addWidget(self.graph)
        self.left_layout.addLayout(self.down_layout)

        self.right_layout=QVBoxLayout()
        self.subtite_layout=QVBoxLayout()
        self.subtite_label=QLabel('音频目录')
        self.subtitle_list=QListWidget()

        self.subtitle_list.clicked.connect(self._audio_dir_click)
        self.subtite_layout.addWidget(self.subtite_label)
        self.subtite_layout.addWidget(self.subtitle_list)
        self.clips_layout=QVBoxLayout()
        self.clips_label=QLabel('音频列表')
        self.clips_list=QListWidget()
        # self.clips_list.setAcceptDrops(True)
        self.clips_list.setDragEnabled(True)
        self.clips_list.setDragDropOverwriteMode(False)
        self.clips_list.setDragDropMode(QAbstractItemView.DragDrop)
        self.clips_list.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.clips_list.setDefaultDropAction(Qt.MoveAction)
        self.clips_list.doubleClicked.connect(self._play_audioclip)
        self.clips_layout.addWidget(self.clips_label)
        self.clips_layout.addWidget(self.clips_list)
        self.right_layout.addLayout(self.subtite_layout)
        self.right_layout.addLayout(self.clips_layout)
        self.right_layout.setStretch(0,1)
        self.right_layout.setStretch(1,5)

        self.main_layout.addLayout(self.left_layout)
        self.main_layout.addLayout(self.right_layout)
        self.setLayout(self.main_layout)






    def setVideoData(self,data):
        self.data=data
        self.timeline.setMaximum(data['frames'])
        self.end_label.setText(str(int(data['frames'])))

    def create_temp_mp4(self):
        temp_path=os.path.join(self.project_dir,'temp')
        temp_mp4=os.path.join(temp_path,'temp.mp4')
        images_path=os.path.join(self.project_dir,'imgs')
        images=os.path.join(images_path,'%d.png')
        cmd = 'ffmpeg -f image2 -i {} -y -vcodec libx264 -r {} {}'.format(images, self.data['fps'], temp_mp4)
        os.popen(cmd)

    def set_project(self,path):
        self.project_dir=path

    def open_project(self):
        if self.project_dir:
            os.startfile(self.project_dir)
        else:
            QMessageBox.information(None,'提示','请先设置工程')

    def timeline_changed(self,value):
        # print(value)
        self.current_frame=value
        self.current_frame_label.setText(str(value))
        self.graph.updateImg(value)   #更新序列
        self.graph.updateSubtitle(value)  #更新字幕

    #音频操作

    def _audio_dir_click(self,index):
        item=self.subtitle_list.itemFromIndex(index)
        text=item.text()
        self._show_clips(text)

    def update_subtitle_list(self):
        if self.project_dir:
            audio_path=os.path.join(self.project_dir,'audioClips')
            audio_dirs=os.listdir(audio_path)
            self.subtitle_list.clear()
            for i in audio_dirs:
                item=QListWidgetItem()
                item.setText(i)
                item.setTextAlignment(Qt.AlignCenter)
                if i in ['default','bgm']:
                    item.setForeground(QBrush(QColor('#FF8C00')))
                self.subtitle_list.addItem(item)


    def _show_clips(self,clip_dir_name):
        """
        选择的音频小目录并显示每个字幕内容。
        /audioClips/1/clip.mp3,clip.txt

        :param clip_dir_name:
        :return:
        """
        self.clip_dir_path = os.path.join(self.project_dir,'audioClips' ,clip_dir_name)
        clips_dirs = os.listdir(self.clip_dir_path)  # 这里列出的是每个按索引序列的文件夹
        clip_data = {}
        if clips_dirs:
            for i in clips_dirs:
                clip_d=os.path.join(self.clip_dir_path,i)
                mp3_path=os.path.join(clip_d,'clip.mp3')
                txt_path=os.path.join(clip_d,'clip.txt')
                clip_data[i]={'mp3':mp3_path,'txt':txt_path}  #存入每个clip目录下对应的mp3与txt信息

            if clip_data:
                try:
                    self.update_clip_list(clip_data)
                except Exception as update_ERR:
                    print(str(update_ERR))

            # else:  #当时选择的是bgm目录时，clips_dirs就是所有的bgm文件
            #     for i in clips_dirs:  #此时的i不再是目录名字，而是bgm的音乐名字
            #         mp3_path=os.path.join(self.clip_dir_path,i)
            #         txt_path=''
            #         clip_data[i]={'mp3':mp3_path,'txt':txt_path}
            #
            #     if clip_data:
            #         try:
            #             self.update_clip_list(clip_data,True)
            #         except Exception as update_ERR:
            #             print(str(update_ERR))

    def update_clip_list(self,clip_data):
        """
        更新右侧的audio列表
        :param clip_data: {'0':{'mp3':mp3_path,'txt':txt_path},'1':{'mp3':mp3_path,'txt':txt_path}}
        :return:
        """
        self.clips_list.clear()
        # if not isbgm:
        temp_key_list=sorted(clip_data.keys(),key=lambda x:int(x))
        for k in temp_key_list:
            v=clip_data[k]
            txt_path=v['txt']
            data={}
            text=k
            if txt_path:  #如果没有txt_path表示当前选择的是bgm目录
                with open(txt_path,'r',encoding='utf8') as r:
                    data=eval(r.read())
                # print('data:',data)
                subtitle=data['subtitle']
                text=k+'.'+subtitle
            # data['mp3']=v['mp3']
            # data['txt']=v['txt']
            item=QListWidgetItem()
            item.setText(text)
            item.setTextAlignment(Qt.AlignLeft)
            item.setData(5,data)
            self.clips_list.addItem(item)
        # else:  #当选择的是bgm时
        #     for b,d in clip_data.items():
        #         data={}
        #         data['subtitle']=''  #如果选择的是背景音乐那么就不读
        #         text=b
        #         item = QListWidgetItem()
        #         item.setText(text)
        #         item.setTextAlignment(Qt.AlignLeft)
        #         item.setData(5, data)
        #         self.clips_list.addItem(item)

    def _play_audioclip(self,index):
        """
        打开音频
        :param index:
        :return:
        """
        # print(index)
        item=self.clips_list.itemFromIndex(index)
        data=item.data(5)
        subtitle=data['subtitle']
        if subtitle:
            self.engine.say(subtitle)  #现阶段只能卡屏幕播放了，因为多线程播放会崩溃
            self.engine.runAndWait()


if __name__ == '__main__':
    app=QApplication(sys.argv)

    # t=ConvertProgress()
    try:
        r_w = StartRefreshMovie()
        r_w.show()
        from widgets.subtitleWindow import SubtitleWindow
        from moviepy.editor import AudioClip, AudioFileClip, concatenate_audioclips, CompositeAudioClip, \
            ImageSequenceClip, VideoFileClip, TextClip, CompositeVideoClip

        t = TimeLine()
        t.show()
        r_w.finish(t)
        r_w.deleteLater()

    except Exception as _err:
        print(str(_err))
    sys.exit(app.exec_())


